#ifndef CLIENT_H
#define CLIENT_H

#include <string>
using std::string;

#include <vector>
using std::vector;

enum Sex
{
	male,
	female
};

enum Region
{
	inner_city,
	rural,
	suburban,
	town
};

enum IncomeClass
{
	low = 0,             //0-19999
	middle_low = 20000,  //20000-39999
	middle = 40000,      //40000-69999
	middle_high = 70000, //70000-89999
	high = 90000         //90000+
};

enum AgeGroup
{
	youngster = 0,      //0-17
	younger_adult = 18, //18-24
	young_adult = 25,   //25-39
	adult = 40,         //40-54
	old_adult = 55,     //55-64
	older_adult = 65    //65+
};

struct Client
{
	Client(const string& id, short age, Sex sex, Region region, double income, bool isMarried, short children, bool hasCar, bool hasSavingAccount, bool hasCurrentAccount, bool hasMortage, bool hasPEP)
	{
		this->id = id;
		this->age = age;
		ageGroup = (age >= older_adult) ? older_adult : 
			       (age >= old_adult) ? old_adult : 
				   (age >= adult) ? adult : 
				   (age >= young_adult) ? young_adult : 
				   (age >= younger_adult) ? younger_adult : youngster;
		this->sex = sex;
		this->region = region;
		this->income = income;
		incomeClass = (income >= high) ? high : 
			          (income >= middle_high) ? middle_high : 
					  (income >= middle) ? middle : 
					  (income >= middle_low) ? middle_low : low;
		this->isMarried = isMarried;
		this->children = children;
		this->hasCar = hasCar;
		this->hasSavingAccount = hasSavingAccount;
		this->hasCurrentAccount = hasCurrentAccount;
		this->hasMortage = hasMortage;
		this->hasPEP = hasPEP;

		computeCategoricVector();
		computeNumericVector();
	}

	Client()
	{
		this->id = "ID0000";
		this->age = 0;
		ageGroup = youngster;
		this->sex = female;
		this->region = inner_city;
		this->income = 0;
		incomeClass = low;
		this->isMarried = false;
		this->children = 0;
		this->hasCar = false;
		this->hasSavingAccount = false;
		this->hasCurrentAccount = false;
		this->hasMortage = false;
		this->hasPEP = false;

		computeCategoricVector();
		computeNumericVector();
	}

	string ageGroup_str() const
	{
		string str;
		switch (ageGroup)
		{
			case youngster:
				str = "youngster";
				break;
			case younger_adult:
				str = "younger_adult";
				break;
			case young_adult:
				str = "young_adult";
				break;
			case adult:
				str = "adult";
				break;
			case old_adult:
				str = "old_adult";
				break;
			case older_adult:
				str = "older_adult";
				break;
		}
		return str;
	}

	string sex_str() const
	{
		string str;
		switch (sex)
		{
			case male:
				str = "male";
				break;
			case female:
				str = "female";
				break;
		}
		return str;
	}

	string region_str() const
	{
		string str;
		switch (region)
		{
			case inner_city:
				str = "inner_city";
				break;
			case rural:
				str = "rural";
				break;
			case suburban:
				str = "suburban";
				break;
			case town:
				str = "town";
				break;
		}
		return str;
	}

	string incomeClass_str() const
	{
		string str;
		switch (incomeClass)
		{
			case low:
				str = "low";
				break;
			case middle_low:
				str = "middle_low";
				break;
			case middle:
				str = "middle";
				break;
			case middle_high:
				str = "middle_high";
				break;
			case high:
				str = "high";
				break;
		}
		return str;
	}

	string id;
	short age;
	AgeGroup ageGroup;
	Sex sex;
	Region region;
	double income;
	IncomeClass incomeClass;
	bool isMarried;
	short children;
	bool hasCar;
	bool hasSavingAccount;
	bool hasCurrentAccount;
	bool hasMortage;
	bool hasPEP;

	static const int INDEX_AGE = 0;
	static const int INDEX_SEX = 1;
	static const int INDEX_REGION = 2;
	static const int INDEX_INCOME = 3;
	static const int INDEX_MARRIED = 4;
	static const int INDEX_CHILDREN = 5;
	static const int INDEX_CAR = 6;
	static const int INDEX_SAVING_ACCOUNT = 7;
	static const int INDEX_CURRENT_ACCOUNT= 8;
	static const int INDEX_MORTAGE = 9;
	static const int INDEX_PEP = 10;

	vector<double> getCategoricVector() const
	{
		return _categoricVector;
	}

	vector<double> getNumericVector() const
	{
		return _numericVector;
	}

private:
	vector<double> _categoricVector;
	vector<double> _numericVector;

	void computeCategoricVector()
	{
		_categoricVector.resize(11);
		switch (ageGroup)
		{
			case youngster:
				_categoricVector[INDEX_AGE] = 0.0;
				break;
			case younger_adult:
				_categoricVector[INDEX_AGE] =  1.0;
				break;
			case young_adult:
				_categoricVector[INDEX_AGE] = 2.0;
				break;
			case adult:
				_categoricVector[INDEX_AGE] = 3.0;
				break;
			case old_adult:
				_categoricVector[INDEX_AGE] = 4.0;
				break;
			case older_adult:
				_categoricVector[INDEX_AGE] = 5.0;
				break;
		}
		sex == male ? _categoricVector[INDEX_SEX] = 0.0 : _categoricVector[INDEX_SEX] = 1.0;
		switch (region)
		{
			case inner_city:
				_categoricVector[INDEX_REGION] = 0.0;
				break;
			case rural:
				_categoricVector[INDEX_REGION] = 1.0;
				break;
			case suburban:
				_categoricVector[INDEX_REGION] = 2.0;
				break;
			case town:
				_categoricVector[INDEX_REGION] = 3.0;
				break;
		}
		switch (incomeClass)
		{
			case low:
				_categoricVector[INDEX_INCOME] = 0.0;
				break;
			case middle_low:
				_categoricVector[INDEX_INCOME] = 1.0;
				break;
			case middle:
				_categoricVector[INDEX_INCOME] = 2.0;
				break;
			case middle_high:
				_categoricVector[INDEX_INCOME] = 3.0;
				break;
			case high:
				_categoricVector[INDEX_INCOME] = 4.0;
				break;
		}
		isMarried ? _categoricVector[INDEX_MARRIED] = 1.0 : _categoricVector[INDEX_MARRIED] = 0.0;
		_categoricVector[INDEX_CHILDREN] = children;
		hasCar ? _categoricVector[INDEX_CAR] = 1.0 : _categoricVector[INDEX_CAR] = 0.0;
		hasSavingAccount ? _categoricVector[INDEX_SAVING_ACCOUNT] = 1.0 : _categoricVector[INDEX_SAVING_ACCOUNT] = 0.0;
		hasCurrentAccount ? _categoricVector[INDEX_CURRENT_ACCOUNT] = 1.0 : _categoricVector[INDEX_CURRENT_ACCOUNT]  = 0.0;
		hasMortage ? _categoricVector[INDEX_MORTAGE] = 1.0 : _categoricVector[INDEX_MORTAGE] = 0.0;
		hasPEP ? _categoricVector[INDEX_PEP] = 1.0 : _categoricVector[INDEX_PEP] = 0.0;
	}
	
	void computeNumericVector()
	{
		_numericVector.resize(11);
		
		_numericVector[INDEX_AGE] = age;
		sex == male ? _numericVector[INDEX_SEX] = 0.0 : _numericVector[INDEX_SEX] = 1.0;
		switch (region)
		{
			case inner_city:
				_numericVector[INDEX_REGION] = 0.0;
				break;
			case rural:
				_numericVector[INDEX_REGION] = 1.0;
				break;
			case suburban:
				_numericVector[INDEX_REGION] = 2.0;
				break;
			case town:
				_numericVector[INDEX_REGION] = 3.0;
				break;
		}
		_numericVector[INDEX_INCOME] = income;
		isMarried ? _numericVector[INDEX_MARRIED] = 1.0 : _numericVector[INDEX_MARRIED] = 0.0;
		_numericVector[INDEX_CHILDREN] = children;
		hasCar ? _numericVector[INDEX_CAR] = 1.0 : _numericVector[INDEX_CAR] = 0.0;
		hasSavingAccount ? _numericVector[INDEX_SAVING_ACCOUNT] = 1.0 : _numericVector[INDEX_SAVING_ACCOUNT] = 0.0;
		hasCurrentAccount ? _numericVector[INDEX_CURRENT_ACCOUNT] = 1.0 : _numericVector[INDEX_CURRENT_ACCOUNT]  = 0.0;
		hasMortage ? _numericVector[INDEX_MORTAGE] = 1.0 : _numericVector[INDEX_MORTAGE] = 0.0;
		hasPEP ? _numericVector[INDEX_PEP] = 1.0 : _numericVector[INDEX_PEP] = 0.0;
	}
};

#endif
